package avicit.bdp.dds.api.controller;

import avicit.bdp.common.dto.query.dds.LogQuery;
import avicit.bdp.dds.api.service.LoggerService;
import avicit.bdp.dds.api.service.ProcessInstanceService;
import avicit.bdp.dds.api.service.TaskInstanceService;
import avicit.bdp.dds.api.service.TaskLogService;
import avicit.bdp.dds.dao.entity.ProcessInstance;
import avicit.bdp.dds.dao.entity.TaskInstance;
import avicit.bdp.dds.dao.entity.TaskLog;
import avicit.platform6.core.exception.BusinessException;
import avicit.platform6.core.rest.msg.ResponseMsg;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
import java.util.Map;

/**
 * 任务日志REST接口
 */
@RestController
@Api(tags = "任务日志REST接口")
@RequestMapping("/api/bdp/dds/log")
public class LoggerRest {

    private static final Logger logger = LoggerFactory.getLogger(LoggerRest.class);

    @Autowired
    private LoggerService loggerService;
    @Autowired
    private TaskLogService taskLogService;
    @Autowired
    private TaskInstanceService taskInstanceService;
    @Autowired
    private ProcessInstanceService processInstanceService;


    /**
     * 查询日志详情
     */
    @PostMapping(value = "/detail")
    @ApiOperation(value = "查询日志详情")
    public ResponseMsg<String> queryLog(@RequestBody LogQuery logQuery) {
        if (logQuery == null) {
            logger.error("the para is null.");
            throw new BusinessException("the para is null");
        }

        Integer limit = logQuery.getLimit();
        Integer skipNum = logQuery.getSkipLineNum();
        String taskInstanceId = logQuery.getTaskInstanceId();
        if (StringUtils.isBlank(taskInstanceId)) {
            logger.error("taskInstanceId null");
            throw new BusinessException("请检查查询参数。");
        }

        if (limit == null || skipNum == null) {
            logger.error("limit or skipNum is null.");
            throw new BusinessException("请检查查询参数。");
        }

        logger.info("view {} task instance log ,skipLineNum {} , limit {}", taskInstanceId, skipNum, limit);

        return loggerService.queryLog(taskInstanceId, skipNum, limit);
    }

    /**
     * 从数据库 查询日志详情
     */
    @PostMapping(value = "/all")
    @ApiOperation(value = "从数据库 查询日志详情")
    public ResponseMsg<String> queryAllLog(@RequestBody LogQuery logQuery) {
        if (logQuery == null) {
            logger.error("the para is null.");
            throw new BusinessException("the para is null");
        }

        String taskInstanceId = logQuery.getTaskInstanceId();
        if (StringUtils.isBlank(taskInstanceId)) {
            logger.error("taskId is null");
            throw new BusinessException("请检查查询参数。");
        }


        logger.info("view {} task instance log", taskInstanceId);
        ResponseMsg<String> responseMsg = new ResponseMsg<>();
        //处理离线计算日志在yarn上的记录
        String content = loggerService.getLogByTaskInstanceId(taskInstanceId, "localLog");
        if (StringUtils.isNotBlank(content)) {
            responseMsg.setResponseBody(content);
            return responseMsg;
        }

        TaskLog taskLog = taskLogService.selectByPrimaryKey(taskInstanceId);
        if (taskLog != null) {
            responseMsg.setResponseBody(taskLog.getContents());
        } else {
            //兼容旧数据
            responseMsg = loggerService.queryAllLog(taskInstanceId);
        }

        return responseMsg;
    }

    /**
     * 查询spark 应用日志
     */
    @PostMapping(value = "/querySparkAppLog")
    @ApiOperation(value = "查询spark 应用日志")
    public ResponseMsg<String> querySparkAppLog(@RequestBody LogQuery logQuery) {
        if (logQuery == null) {
            logger.error("the para is null.");
            throw new BusinessException("the para is null");
        }

        String taskInstanceId = logQuery.getTaskInstanceId();
        if (StringUtils.isBlank(taskInstanceId)) {
            logger.error("taskId is null");
            throw new BusinessException("请检查查询参数。");
        }


        logger.info("view {} task instance log", taskInstanceId);
        ResponseMsg<String> responseMsg = new ResponseMsg<>();
        //处理离线计算日志在yarn上的记录
        String content = loggerService.getLogByTaskInstanceId(taskInstanceId, "app");
        responseMsg.setResponseBody(content);
        return responseMsg;
    }

    /**
     * 查询spark 应用日志
     */
    @PostMapping(value = "/querySparkRunLog")
    @ApiOperation(value = "查询日志详情")
    public ResponseMsg<String> querySparkRunLog(@RequestBody LogQuery logQuery) {
        if (logQuery == null) {
            logger.error("the para is null.");
            throw new BusinessException("the para is null");
        }

        String taskInstanceId = logQuery.getTaskInstanceId();
        if (StringUtils.isBlank(taskInstanceId)) {
            logger.error("taskId is null");
            throw new BusinessException("请检查查询参数。");
        }


        logger.info("view {} task instance log", taskInstanceId);
        ResponseMsg<String> responseMsg = new ResponseMsg<>();
        //处理离线计算日志在yarn上的记录
        String content = loggerService.getLogByTaskInstanceId(taskInstanceId, "run");
        responseMsg.setResponseBody(content);
        return responseMsg;
    }

    /**
     * 查询节点数据
     */
    @PostMapping(value = "/queryFlowData")
    @ApiOperation(value = "查询节点数据")
    public ResponseMsg<List<Map<String, Object>>> queryFlowData(@RequestBody LogQuery logQuery) {
        if (logQuery == null) {
            logger.error("the para is null.");
            throw new BusinessException("the para is null");
        }

        String taskInstanceId = logQuery.getTaskInstanceId();
        if (StringUtils.isBlank(taskInstanceId)) {
            logger.error("taskId is null");
            throw new BusinessException("请检查查询参数。");
        }

        logger.info("view {} task instance log", taskInstanceId);
        ResponseMsg<List<Map<String, Object>>> responseMsg = new ResponseMsg<>();
        //处理离线计算日志在yarn上的记录
        List<Map<String, Object>> content = loggerService.queryFlowData(taskInstanceId);
        responseMsg.setResponseBody(content);
        return responseMsg;
    }

    /**
     * 查询节点分析报告数据
     */
    @PostMapping(value = "/queryFlowAnalysisData")
    @ApiOperation(value = "查询节点分析报告数据")
    public ResponseMsg<Map<String, Object>> queryFlowAnalysisData(@RequestBody LogQuery logQuery) {
        if (logQuery == null) {
            logger.error("the para is null.");
            throw new BusinessException("the para is null");
        }

        String taskInstanceId = logQuery.getTaskInstanceId();
        if (StringUtils.isBlank(taskInstanceId)) {
            logger.error("taskId is null");
            throw new BusinessException("请检查查询参数。");
        }

        logger.info("view {} task instance log", taskInstanceId);
        ResponseMsg<Map<String, Object>> responseMsg = new ResponseMsg<>();
        Map<String, Object> content = loggerService.queryFlowAnalysisData(taskInstanceId);
        responseMsg.setResponseBody(content);
        return responseMsg;
    }

    /**
     * 从数据库查询 翻页
     */
    @PostMapping(value = "/allLogLimit")
    @ApiOperation(value = "查询日志详情")
    public ResponseMsg<String> queryAllLogLimit(@RequestBody LogQuery logQuery) {
        if (logQuery == null) {
            logger.error("the para is null.");
            throw new BusinessException("the para is null");
        }

        String taskInstanceId = logQuery.getTaskInstanceId();
        if (StringUtils.isBlank(taskInstanceId)) {
            logger.error("taskId is null");
            throw new BusinessException("请检查查询参数。");
        }

        Integer limit = logQuery.getLimit();
        Integer skipNum = logQuery.getSkipLineNum();
        if (limit == null || skipNum == null) {
            logger.error("limit or skipNum is null.");
            throw new BusinessException("请检查查询参数。");
        }

        logger.info("view {} task instance log ,skipLineNum {} , limit {}", taskInstanceId, skipNum, limit);

        return loggerService.queryAllLogLimit(taskInstanceId, skipNum, limit);
    }

    /**
     * 下载日志
     */
    @ApiOperation(value = "下载日志")
    @ApiImplicitParam(name = "taskInstanceId", value = "任务实例id", dataType = "String")
    @GetMapping(value = "/download-log")
    public ResponseEntity downloadTaskLog(@RequestParam(value = "taskInstanceId") String taskInstanceId) {
        byte[] logBytes = loggerService.getLogBytes(taskInstanceId);
        return ResponseEntity.ok()
                .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + System.currentTimeMillis() + ".log" + "\"")
                .body(logBytes);
    }


    @PostMapping(value = "/insertTaskLog")
    @ApiOperation(value = "查询日志详情")
    public void insertTaskLog(@RequestBody TaskLog taskLog) {
        if (taskLog == null) {
            logger.error("the para is null.");
            throw new BusinessException("the para is null");
        }

        loggerService.insertTaskLog(taskLog);
    }

    @PostMapping(value = "/updateTaskStatus")
    @ApiOperation(value = "更新任务状态")
    public void updateTaskStatus(@RequestBody TaskInstance taskInstance) {
        if (taskInstance == null) {
            logger.error("the para is null.");
            throw new BusinessException("没有传递参数");
        }
        if (StringUtils.isBlank(taskInstance.getId())) {
            logger.error("taskId is null");
            throw new BusinessException("请检查更新参数。");
        }
        loggerService.updateTaskStatus(taskInstance);
    }

    @PostMapping(value = "/updateProcessStatus")
    @ApiOperation(value = "更新任务状态")
    public void updateProcessStatus(@RequestBody ProcessInstance processInstance) {
        if (processInstance == null) {
            logger.error("the para is null.");
            throw new BusinessException("没有传递参数");
        }
        if (StringUtils.isBlank(processInstance.getId())) {
            logger.error("taskId is null");
            throw new BusinessException("请检查更新参数。");
        }
        loggerService.updateProcessStatus(processInstance);
    }

    @PostMapping(value = "/updateTaskAppId")
    @ApiOperation(value = "更新任务状态")
    public void updateTaskAppId(@RequestBody TaskInstance taskInstance) {
        if (taskInstance == null) {
            logger.error("the para is null.");
            throw new BusinessException("没有传递参数");
        }
        if (StringUtils.isBlank(taskInstance.getProcessInstanceId())) {
            logger.error("taskId is null");
            throw new BusinessException("请检查更新参数。");
        }
        logger.info("更新运行APPID状态：" + taskInstance.getProcessInstanceId() + "-" + taskInstance.getAppLink());

        loggerService.updateTaskAppId(taskInstance);

    }

    @PostMapping(value = "/updateTaskChartResultStatus")
    @ApiOperation(value = "更新任务是否有图片结果的状态")
    public void updateTaskChartResultStatus(@RequestBody TaskInstance taskInstance) {
        if (taskInstance == null) {
            logger.error("the para is null.");
            throw new BusinessException("没有传递参数");
        }
        if (StringUtils.isBlank(taskInstance.getId())) {
            logger.error("taskId is null");
            throw new BusinessException("请检查更新参数。");
        }
        logger.info("更新运行任务状态：" + taskInstance.getProcessInstanceId() + "-" + taskInstance.getId() + "-" + taskInstance.getState());
        taskInstanceService.updateByPrimaryKeySelective(taskInstance);
    }

}
